package com.pb.infra.oth.util;

import com.pb.infra.oth.exception.BizException;
import com.pb.infra.oth.exception.ErrorCode;
import org.apache.commons.lang3.StringUtils;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;

/**
 * 输入参数校验工具类
 *
 * @author 金洋
 * @date 2021/11/18
 */
public final class AssertUtil {

    /**
     * 无参构造器
     */
    AssertUtil() {

    }

    /**
     * 输入字符不能为NULL
     *
     * @param object object
     * @param errorCodeEnum errorCodeEnum
     */
    public static void notNull(Object object, ErrorCode.ErrorCodeEnum errorCodeEnum) {
        if (object == null) {
            throw new BizException(errorCodeEnum.getCode(), errorCodeEnum.getMessage());
        }
    }

    /**
     * 输入字符不能为NULL或空字符串
     *
     * @param input input
     * @param errorCodeEnum errorCodeEnum
     */
    public static void notEmpty(String input, ErrorCode.ErrorCodeEnum errorCodeEnum) {
        if (StringUtils.isEmpty(input)) {
            throw new BizException(errorCodeEnum.getCode(), errorCodeEnum.getMessage());
        }
    }

    /**
     * 输入字符不能为NULL或空字符串或全是空格字符
     *
     * @param input input
     * @param errorCodeEnum errorCodeEnum
     */
    public static void notBlank(String input, ErrorCode.ErrorCodeEnum errorCodeEnum) {
        if (StringUtils.isBlank(input)) {
            throw new BizException(errorCodeEnum.getCode(), errorCodeEnum.getMessage());
        }
    }

    /**
     * 条件判断
     *
     * @param condition condition
     * @param errorCodeEnum errorCodeEnum
     */
    public static void assertTrue(boolean condition, ErrorCode.ErrorCodeEnum errorCodeEnum) {
        condition(condition, errorCodeEnum);
    }

    /**
     * 条件判断
     *
     * @param condition condition
     * @param errorCodeEnum errorCodeEnum
     */
    public static void condition(boolean condition, ErrorCode.ErrorCodeEnum errorCodeEnum) {
        if (!condition) {
            throw new BizException(errorCodeEnum.getCode(), errorCodeEnum.getMessage());
        }
    }

    /**
     * 条件判断
     *
     * @param condition condition
     * @param message message
     */
    public static void checkArgument(boolean condition, String message) {
        condition(condition, message);
    }

    /**
     * 条件判断
     *
     * @param condition condition
     * @param message message
     */
    public static void condition(boolean condition, String message) {
        if (!condition) {
            throw new BizException(message);
        }
    }

    /**
     * 输入字符不能为NULL或空字符串
     *
     * @param input input
     * @param message message
     */
    public static void notEmpty(String input, String message) {
        if (StringUtils.isEmpty(input)) {
            throw new BizException(message);
        }
    }

    /**
     * 输入字符不能为NULL或空字符串或全是空格字符
     *
     * @param input input
     * @param message message
     */
    public static void notBlank(String input, String message) {
        if (StringUtils.isBlank(input)) {
            throw new BizException(message);
        }
    }

    /**
     * 检验集合不能为空
     *
     * @param list 集合对象
     * @param message message
     */
    public static void notEmptyList(List list, String message) {
        if (null == list || list.isEmpty()) {
            throw new BizException(message);
        }
    }

    /**
     * 输入对象不能为空
     *
     * @param input input
     * @param message message
     */
    public static void notNull(Object input, String message) {
        if (null == input) {
            throw new BizException(message);
        }
    }

    /**
     * 输入条件必须成立
     *
     * @param condition condition
     * @param message message
     */
    public static void assertTrue(boolean condition, String message) {
        if (!condition) {
            throw new BizException(message);
        }
    }

    /**
     * 输入条件不成立
     *
     * @param condition condition
     * @param message message
     */
    public static void assertFalse(boolean condition, String message) {
        if (condition) {
            throw new BizException(message);
        }
    }

    /**
     * 输入数值是否与期望值相同
     *
     * @param actual actual
     * @param expected expected
     * @param message message
     */
    public static void assertEquals(int actual, int expected, String message) {
        assertTrue(actual == expected, message);
    }

    /**
     * 输入数值是否在between范围
     *
     * @param actual actual
     * @param begin begin
     * @param end end
     * @param message message
     */
    public static void assertBetween(int actual, int begin, int end, String message) {
        assertTrue(actual >= begin && actual <= end, message);
    }

    /**
     * 输入的字符串长度是否在指定的范围
     *
     * @param input input
     * @param begin begin
     * @param end end
     * @param message message
     */
    public static void assertInputLength(String input, int begin, int end, String message) {
        if (begin > 0) {
            notEmpty(input, message);
        }
        assertBetween(input.length(), begin, end, message);
    }

    /**
     * 输入的字符是否为数字
     *
     * @param input input
     * @param message message
     */
    public static void assertInputDigits(String input, String message) {
        notEmpty(input, message);
        assertTrue(input.matches("\\d+$"), message);
    }

    /**
     * 指定的查询结果必须存在
     *
     * @param input input
     * @param findKey findKey
     * @param argName argName
     */
    public static void requireFound(Object input, Object findKey, String argName) {
        if (null == input) {
            throw new BizException(String.format("系统未找到指定的[%s],参数值=%s", argName, findKey));
        }
    }

    /**
     * 必输入项检查
     *
     * @param input input
     * @param argName argName
     */
    public static void required(Object input, String argName) {
        AssertUtil.notNull(input, String.format("参数[%s]不能为空", argName));
    }

    /**
     * 必输且输入最大长度控制
     *
     * @param input input
     * @param maxLen maxLen
     * @param argName argName
     */
    public static void requiredAndMaxLen(String input, int maxLen, String argName) {
        required(input, argName);
        limitMaxLenArg(input, maxLen, argName);
    }

    /**
     * 输入最大长度控制
     *
     * @param input input
     * @param maxLen maxLen
     * @param argName argName
     */
    public static void limitMaxLenArg(String input, int maxLen, String argName) {
        if (StringUtils.isEmpty(input)) {
            return;
        }
        AssertUtil.assertInputLength(input, 0, maxLen, String.format("参数[%s]最大长度为：%d", argName, maxLen));
    }

    /**
     * 必输固定长度控制
     *
     * @param input input
     * @param fixedLen fixedLen
     * @param argName argName
     */
    public static void requiredAndFixedLen(String input, int fixedLen, String argName) {
        required(input, argName);
        AssertUtil.assertInputLength(input, fixedLen, fixedLen, String.format("参数[%s]长度必须为：%d", argName, fixedLen));
    }

    /**
     * 不能小于当天日期
     *
     * @param input
     * @param message message
     */
    public static void notLessToday(Date input, String message) {
        Date today = DateTimeUtilNew.getNowDatePart();
        if (input.getTime() < today.getTime()) {
            throw new BizException(message);
        }
    }

    /**
     * 必须大于或等于当天日期
     *
     * @param input input
     * @param argName argName
     */
    public static void requiredGteToday(Date input, String argName) {
        required(input, argName);
        notLessToday(input, String.format("参数[%s]不能小于当天", argName));
    }

    /**
     * 检验两个BigDecimal必须相同
     *
     * @param value1 value1
     * @param value2 value2
     * @param message message
     */
    public static void assertEquals(BigDecimal value1, BigDecimal value2, String message) {
        if (value1.compareTo(value2) != 0) {
            throw new BizException(message);
        }
    }

}
